#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<memory.h>
#include<iostream>
#include<strings.h>
#include<functional>
#include<string>
#include"ThreadPool.hpp"
#include"netAddr.hpp"
#include"Log.hpp"
const int Default=-1;
using namespace MutexMudole;
using func_t =std::function<void(int sockfd,const std::string &msg,netAddr &msg_sender)>;
class UdpSocket{
    public:
    UdpSocket(int port,func_t func):_port(port),_sockfd(Default),_isrunning(false),_func(func){}
    void Init(){
         _sockfd=socket(AF_INET,SOCK_DGRAM,0);//创建套接字，AF_INET表示IPv4协议，SOCK_DGRAM表示UDP协议
        if(_sockfd==-1){
            std::cerr<<"create socket error"<<std::endl;
        }
        std::cout<<"create socket success"<<std::endl;
        //绑定socket信息,ip和端口信息
        //填充socketaddr_in结构体
        struct sockaddr_in local;
        //清零结构体
        bzero(&local,sizeof(local));
        //协议族
        local.sin_family=AF_INET;//表示进行网络通信
        local.sin_port=htons(_port);//端口号，网络字节序
        //将ip地址转换为网络字节序
        //local.sin_addr.s_addr=inet_addr(_ip.c_str());//IP地址
        local.sin_addr.s_addr=INADDR_ANY;
        //绑定socket
        int ret=bind(_sockfd,(struct sockaddr*)&local,sizeof(local));//要先把子类强转为基类
        if(ret==-1){
            std::cerr<<"bind socket error"<<std::endl;
            return;
        }
        std::cout<<"bind socket success"<<std::endl;
    }
    void Start(){
        _isrunning=true;
        std::cout<<"start udp socket"<<std::endl;
         
        while(_isrunning){
            char recvbuf[1024]={0};
            //1.收消息ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                // struct sockaddr *src_addr, socklen_t *addrlen);
                //flag标志位:阻塞式IO
                //src_addr:客服端信息
                //addrlen:地址长度，返回时会填充地址长度
            struct sockaddr_in peer;
            socklen_t len=sizeof(peer);
            ssize_t n=recvfrom(_sockfd,recvbuf,sizeof(recvbuf),0,(struct sockaddr*)&peer,&len);
            LockGuard lock(_mutex);
            if(n>=0){
                
                netAddr addr(peer);
                recvbuf[n]='\0';
                
                //2.发消息ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      //const struct sockaddr *dest_addr, socklen_t addrlen);
                //udp是全双工的
                std::string buf(recvbuf);
                _func(_sockfd,buf,addr);
                LOG(LogLevel::DEBUG)<<recvbuf;
            }
        }
    }
    void Stop(){
        _isrunning=false;
    }
    ~UdpSocket(){
        close(_sockfd);
    }
    uint16_t _port;
    int _sockfd;

    bool _isrunning;
    func_t _func;
    Mutex _mutex;
};